/**
 * @(#)ArchivosUtil.java 2/04/2009
 *
 * Copyright (c) 2005-2010 PsiqueWare S.A. de C.V. All Rights Reserved.
 * This software is the proprietary information PsiqueWare S.A. de C.V.
 * Use is subject to license terms.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * <br/>Usuario : AngelElectrico
 * <br/>Creaci&oacute;n: 2/04/2009 - 08:16:04 AM
 * <br/>
 * <br/>
 * <br/><t5>Cambios :</t5>
 * <br/><b>Fecha | Autor  |  Cambios</b>
 * <ul>
 * <li>2/04/2009 | <a href = "mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a> | Creaci&oacute;n del Objeto.</li>
 *
 * </ul>
 */

package com.psiqueware.alheli.basico.util;

import java.io.*;

/**
 * Utilidad de archivos.
 * <br/>Paquete Original: com.psiqueware.orquidea.gui.util
 * <br/>Nombre  Original: ArchivosUtil
 * <br/>Oprima para ver : <a href="ArchivosUtil.java.html"><i>C&oacute;digo Fuente</i> </a>
 *
 * @author <a href="mailto:AngelElectrico@PsiqueWare.com">Angel El&eacute;ctrico</a>
 * @version Revision: 1.1 2/04/2009 08:16:04 AM
 * @noinspection UnusedDeclaration
 */
public final class ArchivosUtil
{

    /**
     * Constructor de ArchivosUtil.
     */
    public ArchivosUtil()
    {
    }

    /**
     * Escribe un texto.
     *
     * @param archivo A escribir.
     * @param texto   A escribir.
     *
     * @throws IOException en caso de un error al escribir.
     */
    public static void escribirTextoRapido(final File archivo, final String texto) throws IOException
    {
//        if (!archivo.exists())
//        {
//            archivo.createNewFile();
//        }

        BufferedWriter bw = null;
        try
        {
            FileWriter fw = new FileWriter(archivo.getAbsoluteFile());
            bw = new BufferedWriter(fw);
            bw.write(texto);
        }
        finally
        {
            if (null != bw) bw.close();
        }
    }

    /**
     * Lee un texto.
     *
     * @param archivo A abrir.
     *
     * @return Cadena con el contenido del archivo.
     *
     * @throws IOException en caso de un error al leer.
     */
    public static String leerTextoRapido(final File archivo) throws IOException
    {

        final StringBuilder sb = new StringBuilder();
        BufferedReader bufferedReader = null;
        try
        {
            final FileReader fileReader = new FileReader(archivo);
            bufferedReader = new BufferedReader(fileReader);
            String line;
            boolean entro = false;
               /*
                * readLine is a bit quirky :
                * it returns the content of a strInstruccion MINUS the newline.
                * it returns null only for the END of the stream.
                * it returns an empty String if two newlines appear in a row.
                */
            while ((line = bufferedReader.readLine()) != null)
            {
                entro = true;
                if (line.isEmpty())
                {
                    sb.append('\n').append('\n');
                }
                else
                {
                    sb.append(line).append('\n');
                }
            }
            if (entro) sb.deleteCharAt(sb.length() - 1);
        }
        finally
        {
            if (null != bufferedReader) bufferedReader.close();
        }
        return sb.toString();
    }

    /**
     * Genera un arreglo de bytes que representa el archivo.
     *
     * @param archivo que se va a convertir en arreglo.
     *
     * @return byte[] generado.
     *
     * @throws IOException en caso de no poder leer el archivo.
     */
    public static byte[] extraerBytesDesdeArchivo(File archivo) throws IOException
    {
        InputStream is = new FileInputStream(archivo);

        // Get the size of the archivo
        long length = archivo.length();

        // You cannot create an array using a long type.
        // It needs to be an int type.
        // Before converting to an int type, check
        // to ensure that archivo is not larger than Integer.MAX_VALUE.
        if (length > Integer.MAX_VALUE)
        {
            // File is too large
            throw new IllegalArgumentException("<error><msg>El archivo es demasiado grande para ser convertido a bytes.</msg></error>");
        }

        // Create the byte array to hold the data
        byte[] bytes = new byte[(int) length];

        // Read in the bytes
        int offset = 0;
        int numRead;
        while (offset < bytes.length
               && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)
        {
            offset += numRead;
        }

        // Ensure all the bytes have been read in
        if (offset < bytes.length)
        {
            throw new IOException("<error><msg>No se termin&oacute; de leer el archivo.</msg><params>" + archivo.getName() + "</params></error>");
        }

        // Close the input stream and return bytes
        is.close();
        return bytes;
    }


    /**
     * Copia un directorio con todos sus archivos de un lugar a otro.
     *
     * @param origen  directorio de origen.
     * @param destino directorio destino.
     *
     * @return <code>true</code> si y solo s&iacute; se copiar&oacute;n exitosamente todos los archivos; <code>false</code> en caso contrario.
     */
    public static boolean copiarRutaCompleta(File origen, File destino)
    {
        boolean salida = true;
        if (origen.isDirectory())
        {
            if (!destino.exists())
            {
                destino.mkdir();
            }

            String[] archivos = origen.list();
            for (final String nombreArchivo : archivos)
            {
                salida = copiarRutaCompleta(new File(origen, nombreArchivo), new File(destino, nombreArchivo));
            }
        }
        else
        {
            salida = copiarArchivos(origen, destino);
        }
        return salida;
    }


    /**
     * Mueve un directorio con todos sus archivos de un lugar a otro.
     *
     * @param origen  directorio de origen.
     * @param destino directorio destino.
     *
     * @return <code>true</code> si la copia y eliminaci&oacute;n del origen fueron exitosas; <code>false</code> en caso contrario.
     */
    public static boolean moverRutaCompleta(final File origen, final File destino)
    {
        return copiarRutaCompleta(origen, destino) && eliminaDirectorio(origen);
    }

    /**
     * Copia un archivo de un lugar a otro.
     *
     * @param origen  archivo de origen.
     * @param destino archivo de destino.
     *
     * @return <code>true</code> si la copia fu&eacute; exitosa; <code>false</code> en caso contrario.
     */
    public static boolean copiarArchivos(final File origen, final File destino)
    {
        if (origen.equals(destino))
            throw new IllegalArgumentException("<error><msg>No se puede copiar un archivo sobre si mismo.</msg>parametros>" + origen + "</parametros></error>");

        FileInputStream from = null;
        FileOutputStream to = null;
        try
        {
            from = new FileInputStream(origen);
            to = new FileOutputStream(destino);
            byte[] buffer = new byte[4096];
            int bytesRead;

            while ((bytesRead = from.read(buffer)) != -1)
            {
                to.write(buffer, 0, bytesRead); // write
                buffer = new byte[4096];
            }
            return true;

        }
        catch (final Exception e)
        {
            final String error = "<error><msg>No se pudo realizar la copia del archivo.</msg><parametros>" + origen + "</parametros></error>";
            System.err.println(error);
            System.err.println(e);
            e.printStackTrace();
        }
        finally
        {
            if (null != from)
                try
                {
                    from.close();
                }
                catch (IOException e)
                {
                    final String error = "<error><msg>No se pudo cerrar el buffer del archivo de origen.</msg><parametros>" + origen + "</parametros></error>";
                    System.err.println(error);
                    System.err.println(e);
                    e.printStackTrace();
                }
            if (null != to)
                try
                {
                    to.close();
                }
                catch (IOException e)
                {
                    final String error = "<error><msg>No se pudo cerrar el buffer del archivo de destino.</msg><parametros>" + origen + "</parametros></error>";
                    System.err.println(error);
                    System.err.println(e);
                    e.printStackTrace();
                }
        }
        return false;
    }

    /**
     * Elimina un directorio y su contenido.
     *
     * @param directorio directorio a eliminar.
     *
     * @return <code>true</code> si se elimino el directorio; <code>false</code> en caso contrario.
     *
     * @noinspection ResultOfMethodCallIgnored
     */
    public static boolean eliminaDirectorio(final File directorio)
    {
        if (directorio.exists())
        {
            File[] files = directorio.listFiles();
            for (final File file : files)
            {
                if (file.isDirectory())
                {
                    eliminaDirectorio(file);
                }
                else
                {
                    file.delete();
                }
            }
        }
        return (directorio.delete());
    }

}

